﻿using System;
using System.Collections.Generic;
using System.Linq;
using ContactManager.Models.Entities;
using Castle.ActiveRecord;
using Castle.ActiveRecord.Queries;
using Castle.ActiveRecord.Framework;
using NHibernate.Criterion;


namespace ContactManager.Models.Repositories
{
    public class ContactManagerRepositoryAr : IContactManagerRepositoryAr
    {
              
        //
        // Query Methods

        public T LoadById<T>(Guid key) where T : class
        {
            return ActiveRecordMediator<T>.FindByPrimaryKey(key, true);
        }

        public IList<T> ListAll<T>() where T : class
        {
            return ActiveRecordMediator<T>.FindAll().ToList<T>();
        }

        public void Create<T>(T instance) where T : class
        {
           
               ActiveRecordMediator<T>.Create(instance);
               return;
        }

        public T GetFirst<T>(ICriterion[] criteria) where T : class
        {
            return ActiveRecordMediator<T>.FindFirst(criteria);
        }

        public IList<T> FindResults<T>(ICriterion[] criteria) where T : class
        {
            return ActiveRecordMediator<T>.FindAll(criteria);
        }
        public IList<Contact> FindContactsBetweenDates(string field, DateTime date1, DateTime date2)
        {

            ICriterion[] criteria = new ICriterion[] 
            {
                Expression.Between(field, date1,date2)   
            };

            IList<Contact> contacts = ActiveRecordMediator<Contact>.FindAll(criteria);
            return contacts;
        }
        public IList<Contact> FindContactsBy(char initial, string field)
        {

            ICriterion[] criteria = new ICriterion[] 
            {
                Expression.Like(field, initial.ToString() + "%")   
            };

            IList<Contact> contacts = ActiveRecordMediator < Contact >.FindAll(criteria);
            return contacts;
        }
        public ContactGroup GetFirstGroup()
        {
            ICriterion[] criteria = new ICriterion[] { Expression.IsNotNull("Id") };
            return ActiveRecordMediator<ContactGroup>.FindFirst(criteria);
        }


        public void Edit<T>(T instance) where T : class
        {
             
            try
            {
                using (TransactionScope tx = new TransactionScope())
                {
                    try
                    {
                        ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(T)).Update(instance);
                        ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(T)).Flush();
                        ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(T)).Evict(instance);
                    }
                    catch (TransactionException exp)
                    {
                        
                        tx.VoteRollBack(); 
                        throw new Exception("Record was not updated due to:" + exp.Message);                      
                    }
                }
               
            }
            catch(Exception e)
            {
                throw new Exception("Record was not updated because:" + e.Message);

            }
        }
        public void Delete<T>(T instance) where T : class
        {
            ActiveRecordMediator<T>.Delete(instance);

        }
        /*
        #region Contact Methods
            //GLOBAL METHODS
            public static IEnumerable<Entities.Contact>ListContacts()
            {
                return ActiveRecordMediator<T>.FindAll().ToList<T>().ToList<
            }
            public static List<Contact> FindAllContacts()
            {
                return Contact.FindAll().ToList<Contact>();
            }
            public static List<Contact> FindTodayContacts()
            {
                DetachedCriteria dateCriteria = null;  
           

                   dateCriteria 

                         .CreateCriteria("Contacts", "contact") 

                         .Add(Expression.Eq("DateEntered", DateTime.Today));




                   return Contact.FindAll(dateCriteria).ToList<Contact>();

               
            }
            public static Entities.Contact GetContact(Guid contatcId)

            {
                //Creates a NEW -- JUST ONE -  Contact Record
                Entities.Contact c = new Entities.Contact();

                c = Contact.Find(contatcId);
                //SimpleQuery q = new SimpleQuery(typeof(Contact), @" from Contact c where c.Id = ?", id);
                //return (Contact)   Castle.ActiveRecord.ActiveRecordBase.ExecuteQuery(q);
                //c = Entities.Contact.FindOne(Expression.Eq("Id", contatcId));
                return c;
            }

            //INSTANCE METHODS
          
            public Entities.Contact Add(System.Guid groupId, Entities.Contact contactToCreate)
            {

                Entities.ContactGroup _group = Entities.ContactGroup.FindOne(Expression.Eq("Id", groupId));//session.Load(typeof(ContactGroup),groupId);
                //Entities.Contact c = new ContactManager.Models.Entities.Contact();
                contactToCreate.ContactGroup = _group;

                _group.Contacts.Add(contactToCreate);
                contactToCreate.Save();

                return contactToCreate;

            }
            public void EditContact(Contact contactToEdit)
            {
                contactToEdit.Update();
                //Contact originalContact = GetContact(contactToEdit.Id);

                //db.Contacts.Attach(contactToEdit);
                //db.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues, contactToEdit);
                // our design does not have a FK between Consultant and address 
                // as address table is used hold data from many other tables 
                // like Consultant. 
                //db.Contacts.Attach.t_addresses.Attach(pobjAddress); 
                //db.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues, pobjAddress);
                // db.t_bank_records.Attach(pobjBankRecord); db.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues, pobjBankRecord); 
                // db.t_contacts.Attach(pobjContactDetails); db.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues, pobjContactDetails); 
                // db.SubmitChanges();

                //originalContact.ContactGroup = GetGroup(groupID);
                //db.SubmitChanges();
                //return contactToEdit;
                //try
                //{

                 
                    //tt_customer Tcust = context.tt_customers.Single(c => c.Pk == customer.Pk);

                  //  ContactManagerModelDataContext db1 = new ContactManagerModelDataContext();//(ContactManagerModelDataContext) new System.Data.Linq.DataContext(System.Configuration.ConfigurationManager.ConnectionStrings["ContactManagerDBConnectionString"].ConnectionString);
                   //db1.ObjectTrackingEnabled = false;
                    //db1.ObjectTrackingEnabled = false;
                   // Contact dbContact = db.Contacts.SingleOrDefault(d => d.Id == contactToEdit.Id);

                 //Contact dbContact = GetContact(contactToEdit.Id,true);

                    
                    //db1.Contacts.Attach(contactToEdit,true);
                    //context.tt_customers.Attach(customer, Tcust); 
                    
                    
                    //context.SubmitChanges();  
                    
                    //db.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues, contactToEdit);
                    //db1.SubmitChanges();
                    

                //}
                //catch (Exception ex) 
               // {
                 //   Exception exep = ex;
                    //return contactToEdit;
                //}
                
            }
            public void Delete(Contact contact)
            {
                contact.Delete();
                //db.RSVPs.DeleteAllOnSubmit(dinner.RSVPs);
                //db.Contacts.DeleteOnSubmit(contact);
                //db.SubmitChanges();
            }

        #endregion


        //GROUP
        #region ContactGroup Methods
            //GLOBAL METHODS
            public static ContactGroup CreateGroup(ContactGroup groupToCreate)
            {
                //db.AddToGroupSet(groupToCreate);
                //db.Groups.InsertOnSubmit(groupToCreate);
                //db.SubmitChanges();
                return groupToCreate;
            }
            public static List<ContactGroup> ListGroups()
            {
                return ContactGroup.FindAll().ToList<ContactGroup>();
            }
            public static List<ContactGroup> FindAllGroups()
            {
                return ContactGroup.FindAll().ToList<ContactGroup>();
            }
            public static ContactGroup GetFirstGroup()
            {
                //SimpleQuery<ContactGroup> query = new SimpleQuery<ContactGroup>("select top 1 * FROM ContactGroups g ORDERBY g.GroupId");
                //ICriterion[] query = { Expression.IsNotNull("Id",) };
                //Order[] sortOrderIs = { Order.Asc("Id")};

    //return Contact.FindAll(sort, query);

               //Contact cw = Contact.FindOne(Expression.Sql("Select max Id ));
               //ContactGroup.FindOne(Expression.IsNotNull("Username"));

                //Session.QueryOver<ContactGroup> maximumAge = QueryOver.Of<ContactGroup>().Select(p => p.SelectMax(c => c.Age));


                //ContactGroup c = Session.QueryOver<ContactGroup>().Where(s => s.Name == "Fabio").And(s => s.StudentNumber > 100).List();

                //ContactGroup c = query.Execute();

                List<ContactGroup> cg = ContactGroup.FindAll().ToList<ContactGroup>();

                return cg[0];
            }
            public static ContactGroup GetGroup(System.Guid id)
            {
                Entities.ContactGroup c = new Entities.ContactGroup();

                c = ContactGroup.Find(id);

                return c;
                
            }
            //INSTANCE METHODS
            public ContactGroup EditGroup(ContactGroup groupToEdit)
            {
                groupToEdit.Update();
                return groupToEdit;
            }        
            public void DeleteGroup(ContactGroup groupToDelete)
            {
                groupToDelete.DeleteAndFlush();

            }
        #endregion

 */
    }
}

       